/********************************************************************
 * Filename:	Device.c
 * Description: The device and related operations.
 * Group 2:		nachOS
 * Author(s):	Jan Durakiewicz
 * Class:		CSE 325
 * Instructor:	David Duggan
 * Assignment:	Lab #8 File System Implementation
 * Assigned:	4/16/2013
 * Due:			4/30/2013
 ********************************************************************/

#include "Device.h"


int get_block_allocation(SEGTYPE blockNumber){
	return device_read_bit(blockNumber + useArrayStart);
}

void set_block_allocation(SEGTYPE blockNumber, int isAllocated){
	//printf("Marking block %llu as %d\n", blockNumber, isAllocated);
	device_write_bit(blockNumber + useArrayStart, isAllocated);
}

void format_device(int _blockSize){
	int i;

	blockSize = _blockSize;
	blockCount = DEVICE_SIZE / (blockSize);	
	blockAddressWidth = logb2(blockCount);
	useArrayStart = FSIB_SIZE;					//starts on this bit
	useArrayEnd = useArrayStart + blockCount;	//ends on this bit

	//printf("Block Count : %d\n", blockCount);

	devicePointer = (SEGTYPE*)malloc(DEVICE_SIZE);

	for(i = 0; i < SEGMENT_COUNT; i++){
		devicePointer[i] = (SEGTYPE) 0;
	}

	//mark FSIB blocks as used
	for(i = 0; i < useArrayEnd/(blockSize*8) + 1; i++){
		set_block_allocation(i, 1);
	}
}

int device_read_bit(SEGTYPE bitNumber){
	int segment = bitNumber / SEGMENT_WIDTH;	//find segment that bit is in
	int bit = bitNumber % SEGMENT_WIDTH;		//find which bit it is
	if((devicePointer[segment] >> bit)%2 == 1)
		return 1;
	
	return 0;
}

void device_write_bit(SEGTYPE bitNumber, int value){
	int segment = bitNumber / SEGMENT_WIDTH;
	int bit = bitNumber % SEGMENT_WIDTH;
	SEGTYPE writeMask = (SEGTYPE)1 << bit;

	if(value == 1){
		devicePointer[segment] = (devicePointer[segment] | (writeMask));
	}
	else
		devicePointer[segment] = devicePointer[segment] & ~(writeMask);
}

/* void print_device(int startIndex, int bitCount){
	int i;
	for(i = startIndex + 1; i <= startIndex + bitCount - 1; i++){
		//printf("%d", device_read_bit(i - 1));
		if(i % SEGMENT_WIDTH == 0)
			printf("\n");
		if(i % (SEGMENT_WIDTH/2) == 0)
			printf("\n[%d]",i);
		else if(i % 8 == 0)
			printf(" ");
		else if(i % 4 == 0)
			printf("-");
	}
}
*/

int logb2(int x){
	return ceil(log((double)x)/log((double)2));
}